package com.xiaolei.fastnio.http.Protocol

import com.xiaolei.fastnio.http.Comm.RequestMethod
import com.xiaolei.fastnio.http.Request
import com.xiaolei.fastnio.library.Client.Session
import okio.Buffer

/**
 * 把数据解析成Request的解码器
 */
class RequestProtocol : HttpRequestCacheProtocol()
{
    private var position = DecodePosition.METHOD

    override fun decodeRequest(session: Session, buffer: Buffer, request: Request): Request?
    {
        readMethod(buffer, request)
        readHeaders(buffer, request)
        readBody(buffer, request)
        return if (position == DecodePosition.DONE) request else null
    }

    /**
     * 读取请求方式
     */
    private fun readMethod(buffer: Buffer, request: Request)
    {
        if (position == DecodePosition.METHOD)
        {
            val line = buffer.readUtf8Line()
            if (line != null && line.isNotEmpty())
            {
                val splits = line.split(" ")
                request.method = splits[0]
                request.uri = splits[1]
                request.scheme = splits[2]
                position = DecodePosition.HEAD
            }
        }
    }

    /**
     * 读取头
     */
    private fun readHeaders(buffer: Buffer, request: Request)
    {
        if (position == DecodePosition.HEAD)
        {
            val line = buffer.readUtf8Line()
            when
            {
                line == null -> Unit
                line.isEmpty() -> position = DecodePosition.BODY
                else ->
                {
                    val splits = line.split(":")
                    val key = splits[0].trim()
                    val content = splits[1].trim()
                    request[key] = content
                    readHeaders(buffer, request)
                }
            }
        }
    }

    /**
     * 读取体
     */
    private fun readBody(buffer: Buffer, request: Request)
    {
        if (position == DecodePosition.BODY)
        {
            when (request.method)
            {
                RequestMethod.POST.name ->
                {
                    val byteArray = buffer.readByteArray()
                    request.body.append(byteArray, 0, byteArray.size)
                    if (request.body.size >= request.contentLength)
                    {
                        position = DecodePosition.DONE
                    }
                }
                else ->
                {
                    position = DecodePosition.DONE
                }
            }
        }
    }

    override fun onClear()
    {
        position = DecodePosition.METHOD
        super.onClear()
    }

    enum class DecodePosition(desc: String)
    {
        METHOD("请求方式"),
        HEAD("请求头"),
        BODY("内容体"),
        DONE("读取结束")
    }
}